import { DaHuaICCBaseService } from "./base";
import { dahua } from "./type";

/**
 * 大华ICC门禁管理服务
 */
export class AccessControlService extends DaHuaICCBaseService {
	/**
	 * 批量按人新增授权
	 * @description 按人员授权接口，支持批量授权，人员所带的卡、指纹、人脸会自动下发
	 * @param data 授权参数
	 * @returns 授权结果
	 */
	async batchAuthority(data: dahua.icc.access.IBatchAuthorityRequest) {
		// 参数验证
		if (!data.personCodes || data.personCodes.length === 0) {
			throw new Error("人员编号列表不能为空");
		}
		if (data.personCodes.length > 1000) {
			throw new Error("人员编号列表最多支持1000个");
		}
		if (!data.privilegeDetails || data.privilegeDetails.length === 0) {
			throw new Error("授权对象列表不能为空");
		}
		if (data.privilegeDetails.length > 1000) {
			throw new Error("授权对象列表最多支持1000个");
		}

		// 计算授权规模
		const totalAuthorities = data.personCodes.length * data.privilegeDetails.length;
		if (totalAuthorities > 500000) {
			throw new Error("授权规模超过限制：人员数量 * 门禁通道数量不能超过50万");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/personAuthority/batchAuthority`;
		const res = await this.curl<dahua.icc.IResponse<void>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data,
		});
		this.handleResponseException(res);
		return res.data.success;
	}

	/**
	 * 按部门新增授权
	 * @description 按部门授权接口，支持多部门按通道和门组批量授权
	 * @param data 授权参数
	 * @returns 授权结果
	 */
	async departmentAuthority(data: dahua.icc.access.IDepartmentAuthorityRequest) {
		// 参数验证
		if (!data.deptIds || data.deptIds.length === 0) {
			throw new Error("部门ID列表不能为空");
		}
		if (data.deptIds.length > 1000) {
			throw new Error("部门ID列表最多支持1000个");
		}
		if ((!data.channelCodes || data.channelCodes.length === 0) && (!data.doorGroupIds || data.doorGroupIds.length === 0)) {
			throw new Error("通道编码列表和门组ID列表不能同时为空");
		}
		if (data.channelCodes && data.channelCodes.length > 1000) {
			throw new Error("通道编码列表最多支持1000个");
		}
		if (data.doorGroupIds && data.doorGroupIds.length > 1000) {
			throw new Error("门组ID列表最多支持1000个");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/deptAuthority`;
		const res = await this.curl<dahua.icc.IResponse<void>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data,
		});
		this.handleResponseException(res);
		return res.data.success;
	}

	/**
	 * 按部门删除授权
	 * @description 按部门删除授权接口，支持删除指定部门的通道和门组授权
	 * @param data 删除授权参数
	 * @returns 删除结果
	 */
	async deleteDepartmentAuthority(data: dahua.icc.access.IDeleteDepartmentAuthorityRequest) {
		// 参数验证
		if (!data.deptId) {
			throw new Error("部门ID不能为空");
		}
		if (
			(!data.deleteChannelCodes || data.deleteChannelCodes.length === 0) &&
			(!data.deleteDoorGroupIds || data.deleteDoorGroupIds.length === 0)
		) {
			throw new Error("要删除的通道编码列表和门组ID列表不能同时为空");
		}
		if (data.deleteChannelCodes && data.deleteChannelCodes.length > 1000) {
			throw new Error("要删除的通道编码列表最多支持1000个");
		}
		if (data.deleteDoorGroupIds && data.deleteDoorGroupIds.length > 1000) {
			throw new Error("要删除的门组ID列表最多支持1000个");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/deptAuthority/delete`;
		const res = await this.curl<dahua.icc.IResponse<void>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data,
		});
		this.handleResponseException(res);
		return res.data.success;
	}

	/** 删除单个权限 */
	async deleteSinglePrivilege(params: dahua.icc.access.IDeleteSinglePrivilegeRequest) {
		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/personAuthority/deleteSinglePrivilege`;
		const res = await this.curl<dahua.icc.IResponse<void>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data: params,
		});
		this.handleResponseException(res);
		return res.data.success;
	}

	/**
	 * 查询授权信息列表
	 * @description 查询授权信息（包含人员拥有的所有权限信息）, 支持分页
	 * @param data 查询参数
	 * @returns 授权信息分页查询结果
	 */
	async queryAuthorityList(data: dahua.icc.access.IAuthorityListRequest) {
		// 参数验证
		if (!data.pageNum || data.pageNum <= 0) {
			throw new Error("页码必须大于0");
		}
		if (!data.pageSize || data.pageSize <= 0) {
			throw new Error("每页记录数必须大于0");
		}
		if (data.pageSize > 100) {
			throw new Error("每页记录数最大支持100");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/syncMultiple/page`;
		const res = await this.curl<dahua.icc.IResponse<dahua.icc.access.IAuthorityListResponse>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data,
		});
		this.handleResponseException(res);
		return res.data.data;
	}

	/**
	 * 查询部门权限配置
	 * @description 查询部门权限配置，返回部门权限配置的通道或门组信息
	 * @param data 查询参数
	 * @returns 部门权限配置信息列表
	 */
	async queryDepartmentAuthorityConfig(data: dahua.icc.access.IDepartmentAuthorityConfigRequest) {
		// 参数验证
		if (!data.deptId) {
			throw new Error("部门ID不能为空");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/deptAuthority/bycondition/combined`;
		const res = await this.curl<dahua.icc.IResponse<dahua.icc.access.IAuthorityConfig[]>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data,
		});
		this.handleResponseException(res);
		return res.data.data;
	}

	/**
	 * 判断权限配置是否为通道权限配置
	 * @param config 权限配置信息
	 * @returns 是否为通道权限配置
	 */
	isChannelAuthorityConfig(config: dahua.icc.access.IAuthorityConfig): config is dahua.icc.access.IChannelAuthorityConfig {
		return "channelCode" in config;
	}

	/**
	 * 判断权限配置是否为门组权限配置
	 * @param config 权限配置信息
	 * @returns 是否为门组权限配置
	 */
	isDoorGroupAuthorityConfig(config: dahua.icc.access.IAuthorityConfig): config is dahua.icc.access.IDoorGroupAuthorityConfig {
		return "groupId" in config;
	}

	/**
	 * 批量删除人员权限
	 * @description 批量删除人员的所有权限，删除的权限包括：卡、指纹、人脸
	 * @param data 删除参数
	 * @returns 是否删除成功
	 */
	async batchDeletePersonAuthority(data: dahua.icc.access.IBatchDeletePersonAuthorityRequest) {
		// 参数验证
		if (!data.personCodes || data.personCodes.length === 0) {
			throw new Error("人员编号列表不能为空");
		}
		if (data.personCodes.length > 1000) {
			throw new Error("人员编号列表最多支持1000个");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/personAuthority/deleteBatch`;
		const res = await this.curl<dahua.icc.IResponse<void>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data,
		});
		this.handleResponseException(res);
		return res.data.success;
	}

	/**
	 * 查询人员权限配置
	 * @description 按人员编号查询人员的权限配置记录
	 * @param personCode 人员编号
	 * @returns 人员权限配置信息
	 */
	async queryPersonAuthorityConfig(personCode: string) {
		// 参数验证
		if (!personCode) {
			throw new Error("人员编号不能为空");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/personAuthority/${personCode}`;
		const res = await this.curl<dahua.icc.IResponse<dahua.icc.access.IPersonAuthorityConfig>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data: {},
		});
		this.handleResponseException(res);
		return res.data.data;
	}

	/**
	 * 判断权限配置是否为通道权限
	 * @param detail 权限配置详情
	 * @returns 是否为通道权限
	 */
	isChannelPrivilege(detail: dahua.icc.access.IPersonPrivilegeDetail): boolean {
		return detail.privilegeType === 1;
	}

	/**
	 * 判断权限配置是否为门组权限
	 * @param detail 权限配置详情
	 * @returns 是否为门组权限
	 */
	isDoorGroupPrivilege(detail: dahua.icc.access.IPersonPrivilegeDetail): boolean {
		return detail.privilegeType === 2;
	}

	/**
	 * 门禁记录分页查询
	 * @description 刷卡记录分页查询接口，不支持查询总数和总页数
	 * @param data 查询参数
	 * @returns 刷卡记录分页查询结果
	 */
	async querySwingCardRecords(data: dahua.icc.access.ISwingCardRecordRequest) {
		// 参数验证
		if (!data.pageNum || data.pageNum <= 0) {
			throw new Error("页码必须大于0");
		}
		if (!data.pageSize || data.pageSize <= 0) {
			throw new Error("每页记录数必须大于0");
		}
		if (!data.startSwingTime) {
			throw new Error("刷卡开始时间不能为空");
		}
		if (!data.endSwingTime) {
			throw new Error("刷卡结束时间不能为空");
		}
		if (data.channelCodes && data.channelCodes.length > 500) {
			throw new Error("通道编码列表最多支持500个");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/swingCardRecord/bycondition/combined`;
		const res = await this.curl<dahua.icc.IResponse<dahua.icc.access.ISwingCardRecordResponse>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data,
		});
		this.handleResponseException(res);
		return res.data.data;
	}

	/**
	 * 查询门禁记录详情
	 * @description 根据ID查询刷卡记录详情
	 * @param id 刷卡记录id
	 * @param swingTime 刷卡时间
	 * @returns 刷卡记录详情
	 */
	async getSwingCardRecordDetail(id: string, swingTime: string) {
		// 参数验证
		if (!id) {
			throw new Error("刷卡记录ID不能为空");
		}
		if (!swingTime) {
			throw new Error("刷卡时间不能为空");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/swingCardRecord/${id}?swingTime=${swingTime}`;
		const res = await this.curl<dahua.icc.IResponse<dahua.icc.access.ISwingCardRecordDetail>>(url, {
			method: "get",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
		});
		this.handleResponseException(res);
		return res.data.data;
	}

	/**
	 * 查询门禁记录数量
	 * @description 根据条件查询刷卡记录数量
	 * @param data 查询参数
	 * @returns 刷卡记录数量
	 */
	async getSwingCardRecordCount(data: dahua.icc.access.ISwingCardRecordCountRequest) {
		// 参数验证
		if (!data.pageNum || data.pageNum <= 0) {
			throw new Error("页码必须大于0");
		}
		if (!data.pageSize) {
			throw new Error("分页大小不能为空");
		}
		if (data.channelCodes && data.channelCodes.length > 500) {
			throw new Error("通道编码列表最多支持500个");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/swingCardRecord/bycondition/combinedCount`;
		const res = await this.curl<dahua.icc.IResponse<number>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data,
		});
		this.handleResponseException(res);
		return res.data.data;
	}

	/**
	 * 设备分页查询
	 * @description 分页查询设备信息，支持按设备大类、小类、编码等条件查询
	 * @param query 查询参数
	 * @returns 查询结果
	 */
	async queryDevicePage(query: dahua.icc.Device.DeviceQueryRequest) {
		const url = `${this.config.baseUrl}/evo-apigw/evo-brm/1.2.0/device/subsystem/page`;
		const res = await this.curl<dahua.icc.Device.PageQueryResponse<dahua.icc.Device.DeviceInfoVO>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data: {
				pageNum: query.pageNum,
				pageSize: query.pageSize,
				ownerCodes: query.ownerCodes,
				showChildNodeData: query.showChildNodeData,
				categorys: query.categorys,
				types: query.types,
				deviceCodes: query.deviceCodes,
				deviceSns: query.deviceSns,
				deviceIps: query.deviceIps,
				isOnline: query.isOnline,
				syncVirtualData: query.syncVirtualData,
			},
		});
		this.handleResponseException(res);
		return res.data;
	}

	/**
	 * 设备详情查询
	 * @description 查询设备详细信息
	 * @param deviceCode 设备编码
	 * @returns 设备详细信息
	 */
	async getDeviceDetail(deviceCode: string) {
		if (!deviceCode) {
			throw new Error("设备编码不能为空");
		}

		const url = `${this.config.baseUrl}/evo-apigw/evo-brm/1.0.0/device/${deviceCode}`;
		const res = await this.curl<dahua.icc.Device.DeviceDetailApiResponse>(url, {
			method: "get",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
		});
		this.handleResponseException(res);
		return res.data;
	}

	/** 设备通道分页查询 */
	async getDeviceChannelPage(query: dahua.icc.Device.DeviceChannelQueryRequest) {
		const url = `${this.config.baseUrl}/evo-apigw/evo-brm/1.2.0/device/channel/subsystem/page`;
		const res = await this.curl<dahua.icc.Device.PageQueryResponse<dahua.icc.Device.ChannelInfo>>(url, {
			method: "post",
			headers: {
				Authorization: `bearer ${this.accessToken}`,
			},
			contentType: "json",
			dataType: "json",
			data: {
				...query,
			},
		});
		this.handleResponseException(res);
		return res.data;
	}
}
